﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Secair.Core
{
   public static class GBMessageFormat
    {
        #region 报文结构
        /// <summary>
        /// 启动符
        /// </summary>
        public const int StartFlagLength = 4;

        #region Header
        /// <summary>
        /// 业务流水号
        /// </summary>
        public const int SerialNumberLength = 4;

        /// <summary>
        /// 版本号
        /// </summary>
        public const int VersionLength = 4;

        /// <summary>
        /// 时间标签
        /// </summary>
        public const int MessageDateTimeLength = 12;

        /// <summary>
        /// 源地址
        /// </summary>
        public const int SourceLength = 12;

        /// <summary>
        /// 目标地址
        /// </summary>
        public const int TargetLength = 12;

        /// <summary>
        /// 应用数据单元长度
        /// </summary>
        public const int DataUnitLength = 4;

        /// <summary>
        /// 命令字节
        /// </summary>
        public const int CommandLength = 2;

        /// <summary>
        /// 控制单元长度
        /// </summary>
        public const int controllerUnitLength = 50;
        #endregion

        #region DataUnit
        /// <summary>
        /// 类型标识符
        /// </summary>
        public const int TypeLength = 2;

        /// <summary>
        /// 信息对象数目
        /// </summary>
        public const int MessageObjectCountLength = 2;
        #endregion

        /// <summary>
        /// 校验和
        /// </summary>
        public const int CheckSumLength = 2;

        /// <summary>
        /// 结束符
        /// </summary>
        public const int EndFlagLength = 4;
        #endregion

        /// <summary>
        /// 将报文字符串转换为实体
        /// </summary>
        /// <param name="strUpMessage"></param>
        /// <returns></returns>
        public static GBMessageEntity MessageStringConvertEntity(string strUpMessage)
        {
            try
            {
                GBMessageEntity gbMessageEntity = new GBMessageEntity();

                gbMessageEntity.StartFlag = strUpMessage.Substring(0, StartFlagLength);

                gbMessageEntity.SerialNumber = strUpMessage.Substring(StartFlagLength, SerialNumberLength);
                gbMessageEntity.Version = strUpMessage.Substring(StartFlagLength + SerialNumberLength, VersionLength);
                gbMessageEntity.MessageDateTime = strUpMessage.Substring(StartFlagLength + SerialNumberLength + VersionLength, MessageDateTimeLength);
                gbMessageEntity.Source = strUpMessage.Substring(StartFlagLength + SerialNumberLength + VersionLength + MessageDateTimeLength, SourceLength);
                gbMessageEntity.Target = strUpMessage.Substring(StartFlagLength + SerialNumberLength + VersionLength + MessageDateTimeLength + SourceLength, TargetLength);

                string strDataUnitLength = strUpMessage.Substring(StartFlagLength + SerialNumberLength + VersionLength + MessageDateTimeLength + SourceLength + TargetLength, DataUnitLength);
                gbMessageEntity.DataUnitLength = Convert.ToInt32(littleEndianToBigEndian(strDataUnitLength), 16);

                gbMessageEntity.Command = Convert.ToInt32(strUpMessage.Substring(StartFlagLength + SerialNumberLength + VersionLength + MessageDateTimeLength + SourceLength + TargetLength + DataUnitLength, CommandLength), 16);

                int intDataUnitLength = gbMessageEntity.DataUnitLength;

                //应用数据单元可以为空
                if (intDataUnitLength > 0)
                {
                    gbMessageEntity.Type = Convert.ToInt32(strUpMessage.Substring(controllerUnitLength + StartFlagLength, TypeLength), 16);
                    gbMessageEntity.MessageObjectCount = Convert.ToInt32(strUpMessage.Substring(controllerUnitLength + StartFlagLength + TypeLength, MessageObjectCountLength), 16);
                    gbMessageEntity.MessageObjectContent = strUpMessage.Substring(controllerUnitLength + StartFlagLength + TypeLength + MessageObjectCountLength, intDataUnitLength * 2 - TypeLength - MessageObjectCountLength);
                }
                else
                {
                    gbMessageEntity.Type = -1;//“无锡蓝天”2协议应用单元为空，为心跳协议
                    gbMessageEntity.MessageObjectCount = 0;
                    gbMessageEntity.MessageObjectContent = "";
                }

                gbMessageEntity.CheckSum = strUpMessage.Substring(strUpMessage.Length - 6, CheckSumLength);
                gbMessageEntity.EndFlag = strUpMessage.Substring(strUpMessage.Length - 4, EndFlagLength);

                return gbMessageEntity; 
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 小端转大端，翻转字节顺序
        /// </summary>
        /// <param name="littleEndianString"></param>
        /// <returns></returns>
        private static string littleEndianToBigEndian(string littleEndianString)
        {
            try
            {
                int arrLength = littleEndianString.Length / 2;

                byte[] source = new byte[arrLength];

                for (int i = 0; i < littleEndianString.Length; i += 2)
                {
                    source[i / 2] = (byte)Convert.ToByte(littleEndianString.Substring(i, 2), 16);
                }

                //翻转source数组
                byte[] temp = new byte[arrLength];
                for (int i = 0; i < arrLength; i++)
                {
                    temp[i] = source[arrLength - 1 - i];
                }

                return Secair.Core.ByteHelper.bytesToHexString(temp);
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }
}
